{
 "cells": [
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "\n",
    "\n",
    "# 5、`series`和`dataframe`\n",
    "\n",
    "在 Pandas 中，**Series** 和 **DataFrame** 是最核心的两种数据结构，分别对应一维和二维数据。它们的设计灵感来源于电子表格（如 Excel）和 SQL 表，但提供了更灵活的编程接口。\n",
    "\n",
    "## 5.1核心定义与结构\n",
    "\n",
    "### 5.1.1`Series`：一维带标签的数组\n",
    "\n",
    "- **结构**：由 **数据（Values）** 和 **索引（Index）** 组成。\n",
    "\n",
    "- **类比**：可以看作是一个带有列名的单列 Excel 表格，或一个键值对的字典（但支持向量化操作）。\n",
    "\n",
    "- 示例：\n",
    "\n",
    "  ```python\n",
    "  import pandas as pd\n",
    "  s = pd.Series([10, 20, 30], index=['a', 'b', 'c'], name=\"scores\")\n",
    "  ```\n",
    "\n",
    "  输出：\n",
    "\n",
    "  ```\n",
    "  a    10\n",
    "  b    20\n",
    "  c    30\n",
    "  Name: scores, dtype: int64\n",
    "  ```\n",
    "\n",
    "  - **数据**：`[10, 20, 30]`\n",
    "  - **索引**：`['a', 'b', 'c']`\n",
    "  - **名称**：`\"scores\"`（可选，用于标识 Series）\n",
    "\n",
    "### 5.1.2`DataFrame`：二维表格型数据结构\n",
    "\n",
    "- **结构**：由多个 **Series 组成**（每列是一个 Series），共享同一个行索引（Index）。\n",
    "\n",
    "- **类比**：Excel 表格或 SQL 表，支持行和列的双向索引。\n",
    "\n",
    "- 示例：\n",
    "\n",
    "  ```python\n",
    "  data = {\n",
    "      'Name': ['Alice', 'Bob', 'Charlie'],\n",
    "      'Age': [25, 30, 35],\n",
    "      'City': ['New York', 'London', 'Paris']\n",
    "  }\n",
    "  df = pd.DataFrame(data, index=['r1', 'r2', 'r3'])\n",
    "  ```\n",
    "\n",
    "  输出：\n",
    "\n",
    "  ```tex\n",
    "         Name  Age      City\n",
    "  r1    Alice   25  New York\n",
    "  r2      Bob   30    London\n",
    "  r3  Charlie   35     Paris\n",
    "  ```\n",
    "\n",
    "  - **列**：每列是一个 Series（如 `df['Name']` 是一个 Series）。\n",
    "  - **行索引**：`['r1', 'r2', 'r3']`\n",
    "  - **列索引**：`['Name', 'Age', 'City']`\n",
    "\n",
    "## 5.2关键对比维度\n",
    "\n",
    "| **特性**     | **Series**                       | **DataFrame**                       |\n",
    "| ------------ | -------------------------------- | ----------------------------------- |\n",
    "| **维度**     | 一维（单列）                     | 二维（多列）                        |\n",
    "| **组成**     | 数据 + 索引                      | 多个 Series（列） + 行索引 + 列索引 |\n",
    "| **索引方式** | 仅支持单层索引（行或列二选一）   | 支持行索引和列索引（双向）          |\n",
    "| **典型用途** | 存储时间序列、特征向量、字典替代 | 存储表格数据、数据库查询结果        |\n",
    "| **内存效率** | 更高（单列数据）                 | 较低（多列数据）                    |\n",
    "| **创建方式** | 从列表、字典、标量创建           | 从字典、列表、Series、外部文件创建  |\n",
    "\n",
    "## 5.3详细操作对比\n",
    "\n",
    "### 5.3.1索引与切片\n",
    "\n",
    "#### 1、`Series` 的索引\n",
    "\n",
    "- 标签索引：\n",
    "\n",
    "  ```python\n",
    "  s['a']  # 返回 10\n",
    "  ```\n",
    "\n",
    "- 位置索引：\n",
    "\n",
    "  ```python\n",
    "  s[0]  # 返回 10（第一个元素）\n",
    "  ```\n",
    "\n",
    "- 切片：\n",
    "\n",
    "  ```python\n",
    "  s['a':'b']  # 返回 a→10, b→20（包含末端）\n",
    "  s.iloc[0:2] # 返回 a→10, b→20\n",
    "  ```\n",
    "\n",
    "#### 1、`DataFrame` 的索引\n",
    "\n",
    "- 列索引：\n",
    "\n",
    "  ```python\n",
    "  df['Name']  # 返回 Name 列的 Series\n",
    "  ```\n",
    "\n",
    "- 行索引：\n",
    "\n",
    "  ```python\n",
    "  df.loc['r1']  # 返回 r1 行的 Series\n",
    "  ```\n",
    "\n",
    "- 双向切片：\n",
    "\n",
    "  - 必须使用 `.iloc[]`\n",
    "\n",
    "  ```python\n",
    "  df.loc['r1':'r2', 'Age':'City']  # 返回 r1-r2 行，Age-City 列\n",
    "  df.iloc[0:2, 0:2] # 行切片，列切片\n",
    "  df.loc['r1':'r3', 'Name':'City'] # 行切片，列切片\n",
    "  ```\n",
    "\n",
    "### 5.3.2缺失值处理\n",
    "\n",
    "#### 1、`Series` 的缺失值\n",
    "\n",
    "```python\n",
    "s = pd.Series([1, None, 3])\n",
    "s.isna()       # 检查缺失值：False, True, False\n",
    "s.isnull() \t   # 检查缺失值\n",
    "s.dropna()     # 删除缺失值：0→1, 2→3\n",
    "s.fillna(0)    # 填充缺失值为 0\n",
    "```\n",
    "\n",
    "#### 2、`DataFrame `的缺失值\n",
    "\n",
    "```python\n",
    "df = pd.DataFrame({'A': [1, None, 3], 'B': [4, 5, None]})\n",
    "df.isna()       # 检查每列的缺失值\n",
    "df.dropna()     # 删除含缺失值的行\n",
    "df.fillna(0)    # 填充所有缺失值为 0\n",
    "df.fillna({'A': 10, 'B': 20})  # 按列填充不同值\n",
    "```\n",
    "\n",
    "### 5.3.3统计计算\n",
    "\n",
    "#### 1、`Series `的统计\n",
    "\n",
    "```python\n",
    "s = pd.Series([1, 2, 3, 4, 5])\n",
    "# mean() 会自动忽略 NaN 值（即 None 或 np.nan），仅计算有效数值\n",
    "s.mean()   # 均值：3.0\n",
    "s.sum()    # 求和：15\n",
    "s.max()    # 最大值：5\n",
    "```\n",
    "\n",
    "#### 1、`DataFrame `的统计\n",
    "\n",
    "- 整表统计：\n",
    "\n",
    "  ```python\n",
    "  df.mean()  # 计算每列的均值（忽略非数值列）\n",
    "  ```\n",
    "\n",
    "- 按行统计：\n",
    "\n",
    "  ```python\n",
    "  df.mean(axis=1)  # 计算每行的均值\n",
    "  ```\n",
    "\n",
    "- 分组统计：\n",
    "\n",
    "  ```python\n",
    "  df.groupby('City')['Age'].mean()  # 按城市分组计算平均年龄\n",
    "  ```\n",
    "\n"
   ],
   "id": "6a2994ea71f1cfff"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-08T11:21:24.038158Z",
     "start_time": "2025-08-08T11:21:24.029589Z"
    }
   },
   "cell_type": "code",
   "outputs": [],
   "execution_count": 1,
   "source": "import pandas as pd",
   "id": "fd34d6f31bc16218"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-08T11:21:27.732217Z",
     "start_time": "2025-08-08T11:21:27.724998Z"
    }
   },
   "cell_type": "code",
   "outputs": [],
   "execution_count": 2,
   "source": [
    "s = pd.Series([10, None, 30, None, 40], index=['a', 'b', 'c', 'd', 'e'], name=\"scores\")\n",
    "\n",
    "data = {\n",
    "    'Name': ['Alice', 'Bob', 'Charlie'],\n",
    "    'Age': [25, 30, 35],\n",
    "    'City': ['New York', 'London', 'Paris'],\n",
    "    'Gender': ['F', 'M', None],\n",
    "    'Salary': [5000, 6000, None]\n",
    "}\n",
    "df = pd.DataFrame(data, index=['r1', 'r2', 'r3'])"
   ],
   "id": "19b2e9a49a431795"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-08T10:50:48.582512Z",
     "start_time": "2025-08-08T10:50:48.566752Z"
    }
   },
   "cell_type": "code",
   "source": [
    "display(df)\n",
    "print(\"\\n\")\n",
    "s"
   ],
   "id": "674b5ed744f4ceac",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "       Name  Age      City Gender  Salary\n",
       "r1    Alice   25  New York      F  5000.0\n",
       "r2      Bob   30    London      M  6000.0\n",
       "r3  Charlie   35     Paris   None     NaN"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Age</th>\n",
       "      <th>City</th>\n",
       "      <th>Gender</th>\n",
       "      <th>Salary</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>r1</th>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>New York</td>\n",
       "      <td>F</td>\n",
       "      <td>5000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>r2</th>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>London</td>\n",
       "      <td>M</td>\n",
       "      <td>6000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>r3</th>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>Paris</td>\n",
       "      <td>None</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "a    10.0\n",
       "b     NaN\n",
       "c    30.0\n",
       "d     NaN\n",
       "e    40.0\n",
       "Name: scores, dtype: float64"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 46
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 索引与切片",
   "id": "5459896b0ea3f9ff"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-08T10:37:46.739745Z",
     "start_time": "2025-08-08T10:37:46.729890Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 通过标签索引获取数据\n",
    "# s['a']\n",
    "# 位置索引\n",
    "# s.iloc[0]\n",
    "# s[0]\n",
    "# 切片\n",
    "# s[0:2]\n",
    "# s['a':'c']\n",
    "# dataframe双向切片\n",
    "# df.iloc[0:2, 0:2] # 行切片，列切片\n",
    "df.loc['r1':'r3', 'Name':'City']  # 行切片，列切片"
   ],
   "id": "b4de966f072ef3ce",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "       Name  Age      City\n",
       "r1    Alice   25  New York\n",
       "r2      Bob   30    London\n",
       "r3  Charlie   35     Paris"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Age</th>\n",
       "      <th>City</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>r1</th>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>New York</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>r2</th>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>London</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>r3</th>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>Paris</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 22
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 缺失值处理",
   "id": "5b51ee259025a383"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-08T10:48:14.870356Z",
     "start_time": "2025-08-08T10:48:14.858684Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 检查缺失值\n",
    "# s.isna\n",
    "# 删除缺失值\n",
    "s.dropna()\n",
    "# 填充缺失值\n",
    "s.fillna(0)\n",
    "\n",
    "df.fillna({'Gender': 'U', 'Salary': 0})"
   ],
   "id": "5653ca458561d042",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "       Name  Age      City Gender  Salary\n",
       "r1    Alice   25  New York      F  5000.0\n",
       "r2      Bob   30    London      M  6000.0\n",
       "r3  Charlie   35     Paris      U     0.0"
      ],
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Age</th>\n",
       "      <th>City</th>\n",
       "      <th>Gender</th>\n",
       "      <th>Salary</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>r1</th>\n",
       "      <td>Alice</td>\n",
       "      <td>25</td>\n",
       "      <td>New York</td>\n",
       "      <td>F</td>\n",
       "      <td>5000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>r2</th>\n",
       "      <td>Bob</td>\n",
       "      <td>30</td>\n",
       "      <td>London</td>\n",
       "      <td>M</td>\n",
       "      <td>6000.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>r3</th>\n",
       "      <td>Charlie</td>\n",
       "      <td>35</td>\n",
       "      <td>Paris</td>\n",
       "      <td>U</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 45
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 统计计算\n",
    "- mean() 会自动忽略 NaN 值（即 None 或 np.nan），仅计算有效数值.有效数值的和为 10 + 30 + 40 = 80，数量为 3。DataFrame 的 mean() 方法默认也会跳过 NaN（缺失值），与 Series 的行为一致。\n",
    "- 计算 DataFrame 某一列的均值非常简单\n",
    "    - 方法 1：直接使用列名 + .mean()\n",
    "    - 方法 2：使用 loc 或 iloc 选择列\n",
    "    - 方法 3：计算多列的均值"
   ],
   "id": "6cac96d0e98be1e1"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-08-08T11:18:58.015227Z",
     "start_time": "2025-08-08T11:18:58.000782Z"
    }
   },
   "cell_type": "code",
   "source": [
    "s.mean()\n",
    "s.sum()\n",
    "s.max()\n",
    "\n",
    "# df['Age'].mean()\n",
    "# df['Salary'].mean()\n",
    "# df.loc[:, ['Age', 'Salary']].mean()\n"
   ],
   "id": "31f2663a7ad6f007",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "40.0"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 57
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "b3c1514c45ad07d2"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "c8bda9b41acb9f30"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "7192a0e2a6409277"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "9564f32178d1a12a"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "1764e0d98f926587"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "outputs": [],
   "execution_count": null,
   "source": "",
   "id": "8f490ce1358a07e7"
  },
  {
   "metadata": {},
   "cell_type": "code",
   "source": "",
   "id": "316d88cf2182810f",
   "outputs": [],
   "execution_count": null
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 5
}
